package socket.Serveur;

import java.net.*;
import java.util.Iterator;
import java.io.*;

class ClientThread implements Runnable {
    private Thread         t;            // contiendra le thread du client
    private Socket         mySocket;     // recevra le socket liant au client
    private PrintStream    out;          // pour gestion du flux de sortie
    private BufferedReader in;           // pour gestion du flux d'entrée
    private ServeurThread  serv;         // pour utilisation des méthodes de la
    // classe principale
    private int            numClient = 0; // contiendra le numéro de client géré

    // par ce thread

    // ** Constructeur : crée les éléments nécessaires au dialogue avec le
    // client **
    ClientThread(Socket s, ServeurThread blablaServ) // le param s est donnée
    // dans BlablaServ par
    // ss.accept()
    {
        serv = blablaServ; // passage de local en global (pour gestion dans les
        // autres méthodes)
        mySocket = s; // passage de local en global
        try {
            // fabrication d'une variable permettant l'utilisation du flux de
            // sortie avec des string
            out = new PrintStream(mySocket.getOutputStream());
            // fabrication d'une variable permettant l'utilisation du flux
            // d'entrée avec des string
            in = new BufferedReader(new InputStreamReader(mySocket
                    .getInputStream()));
            // ajoute le flux de sortie dans la liste et récupération de son
            // numero
            numClient = serv.addClient(out);
        } catch (IOException e) {
        }

        t = new Thread(this); // instanciation du thread
        t.start(); // demarrage du thread, la fonction run() est ici lancée
    }

    // ** Methode : exécutée au lancement du thread par t.start() **
    // ** Elle attend les messages en provenance du serveur et les redirige **
    // cette méthode doit obligatoirement être implémentée à cause de
    // l'interface Runnable
    public void run() {
        String message = ""; // déclaration de la variable qui recevra les
        // messages du client
        // on indique dans la console la connection d'un nouveau client
        System.out.println("Un nouveau client s'est connecte, no " + numClient);
        try {
            String line;
            boolean connection = true;
            try {

                out.println("Voici les commandes disponibles : \n");
                out
                        .println("Ajouter une association nom/surnom  :  ADD_<surnom>_<nom>");
                out
                        .println("Supprimer une association nom/surnom : DEL_<surnom>");
                out
                        .println("Modifier un surnom : MODS_<ancien surnom>_<nouveau surnom>");
                out
                        .println("Modifier le nom associé à un surnom : MODN_<surnom>_<nom>");
                out
                        .println("Lister toutes les associations nom/surnom : LISTALL");
                out
                        .println("Lister tous les surnoms associés à un nom : LIST_<nom>");
                out.println("Quitter : QUIT");
                out.println("STOP");

                while ((line = in.readLine()) != null && connection) {
                    String[] tabStr = line.split("_");
                    Services value;
                    try {
                        value = Services.valueOf(tabStr[0]);
                    } catch (Exception e) {
                        value = Services.ERROR;
                    }
                    switch (value) {
                        case ADD:
                            if (tabStr.length < 3) {
                                out.println("ERROR : requête inconnue.");
                                out.println("STOP");
                            } else {
                                String old = serv.addInfo(tabStr[1], tabStr[2]);
                                if (old == null) {
                                    out.println("OK");
                                } else {
                                    out
                                            .println("ERROR_02 : le surnom existe déjà.");
                                    serv.addInfo(tabStr[1], old);
                                }
                                out.println("STOP");
                            }
                            break;
                        case LIST:
                            out.println("ERROR : requête non implémentée.");
                            out.println("STOP");
                            break;
                        case LISTALL:
                            out.println("OK");
                            Iterator<String> i = serv.getInfos().keySet()
                                    .iterator();
                            String cle = null,
                            associe = null;
                            while (i.hasNext()) {
                                cle = (String) (i.next());
                                associe = serv.getInfos().get(cle);
                                out.println("Surnom : " + cle + ", Nom : "
                                        + associe);
                            }
                            out.println("STOP");
                            break;
                        case QUIT:
                            out.println("QUIT");
                            connection = false;
                            break;
                        case MODN:
                            out.println("ERROR : requête non implémentée.");
                            out.println("STOP");
                            break;
                        case MODS:
                            out.println("ERROR : requête non implémentée.");
                            out.println("STOP");
                            break;
                        case DEL:
                            out.println("ERROR : requête non implémentée.");
                            out.println("STOP");
                            break;
                        default:
                            out.println("ERROR : requête inconnue.");
                            out.println("STOP");
                            break;

                    }
                }

            } catch (IOException e) {
                System.out.println(e);
            }
        } catch (Exception e) {
        } finally // finally se produira le plus souvent lors de la deconnexion
        // du client
        {
            try {
                // on indique à la console la deconnexion du client
                System.out.println("Le client no " + numClient
                        + " s'est deconnecte");
                serv.delClient(numClient); // on supprime le client de la liste
                mySocket.close(); // fermeture du socket si il ne l'a pas déjà
                // été (à cause de l'exception levée plus
                // haut)
            } catch (IOException e) {
            }
        }
    }
}